#include "FPCH.h"

#include "FLoaderBM.h"

#include "FKerningTable.h"

namespace Font
{

	LoaderBM::LoaderBM(Library* a_Library) : Loader(a_Library)
	{
		
	}
	
	LoaderBM::~LoaderBM()
	{
		
	}

	bool LoaderBM::LoadDefault()
	{
		return false;
	}

	struct BMComponent
	{
		char name[128];
		char value[128];
	};

	struct BMState
	{

		enum List
		{
			eNone,
			eInfo,
			ePage,
			eChars,
			eCharEntry,
			eKernings,
			eKerningEntry
		};

	};

	Face* LoaderBM::LoadFace(Family* a_Family, const tb::String& a_Settings)
	{
		FILE* handle = fopen(a_Settings.GetData(), "r");
		if (!handle) { return NULL; }

		std::vector<BMComponent> com_list;

		KerningTable* table;
		BMState::List state = BMState::eNone;

		char line[1024];
		while (fgets(line, 1024, handle))
		{
			char ident[16] = { 0 };
			const char* ident_found = strchr(line, ' ');
			int ident_index = ident_found - line;
			strncpy(ident, line, ident_index);

			if (!strcmp(ident, "info"))
			{
				state = BMState::eInfo;
			}
			else if (!strcmp(ident, "chars"))
			{
				state = BMState::eChars;
			}
			else if (state != BMState::eCharEntry && !strcmp(ident, "char"))
			{
				state = BMState::eCharEntry;
			}
			else if (!strcmp(ident, "kernings"))
			{
				state = BMState::eKernings;
				table = new KerningTable(m_Library);
			}
			else if (state != BMState::eKerningEntry && !strcmp(ident, "kerning"))
			{
				state = BMState::eKerningEntry;
			}

			com_list.clear();

			const char* src_line = line + ident_index;
			const char* src_startname = src_line;

			bool eol = false;
			do
			{
				while (*src_startname == ' ')
				{
					src_startname++;
					if (*src_startname == '\n') 
					{ 
						eol = true; 
						break; 
					}
				}

				if (eol) { break; }

				// get name

				BMComponent curr;
				com_list.push_back(curr);

				memset(curr.name, 0, 128);
				const char* src_equals = strchr(src_startname, '=');
				strncpy(curr.name, src_startname, src_equals - src_startname);

				// get value

				memset(curr.value, 0, 128);
				const char* src_startvalue = src_equals + 1;
				const char* src_quote = strchr(src_startvalue, '\"');
				const char* src_endvalue = strchr(src_startvalue, ' ');
				if (src_quote && src_quote < src_endvalue)
				{
					src_endvalue = strchr(src_quote + 1, '\"') + 1;
				}
				if (src_endvalue)
				{
					strncpy(curr.value, src_startvalue, src_endvalue - src_startvalue);
					src_startname = src_endvalue;
				}
				else
				{
					strcpy(curr.value, src_startvalue);
					eol = true;
				}
			}
			while (!eol);

			if (state == BMState::eInfo)
			{
				tb::String name;
				unsigned int size;
				unsigned int style;
				int charset = -1;
				unsigned int size_line = 0;
				//unsigned int texture_width, texture_height;

				for (size_t i = 0; i < com_list.size(); i++)
				{
					if (!strcmp(com_list[i].name, "face"))
					{
						name = com_list[i].value;
					}
					else if (!strcmp(com_list[i].name, "size"))
					{
						size = (unsigned int)atoi(com_list[i].value);
					}
					else if (!strcmp(com_list[i].name, "bold") && !strcmp(com_list[i].value, "1"))
					{
						style |= FWEIGHT_BOLD;
					}
					else if (!strcmp(com_list[i].name, "italic") && !strcmp(com_list[i].value, "1"))
					{
						style |= FSTYLE_ITALIC;
					}
					else if (!strcmp(com_list[i].name, "unicode") && !strcmp(com_list[i].value, "1"))
					{

					}
					else if (!strcmp(com_list[i].name, "lineHeight"))
					{
						size_line = (unsigned int)atoi(com_list[i].value);
					}
				}
			}
			else if (state == BMState::eKerningEntry)
			{
				unsigned int glyph_left, glyph_right;
				int amount;

				for (size_t i = 0; i < com_list.size(); i++)
				{
					if (!strcmp(com_list[i].name, "first"))
					{
						glyph_left = (unsigned int)atoi(com_list[i].value);
					}
					else if (!strcmp(com_list[i].name, "second"))
					{
						glyph_right = (unsigned int)atoi(com_list[i].value);
					}
					else if (!strcmp(com_list[i].name, "amount"))
					{
						amount = atoi(com_list[i].value);
					}
				}

				table->AddEntry(glyph_left, glyph_right, amount);
			}
		}

		fclose(handle);

		return NULL;
	}

	Metrics* LoaderBM::CreateMetrics(Family* a_Family, unsigned int a_Style, CharMap* a_CharMap)
	{
		return NULL;
	}

}; // namespace Font